package com.cruise.game.service.impl.agent;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cruise.game.common.api.ApiException;
import com.cruise.game.mapper.UserMapper;
import com.cruise.game.mapper.WithdrawalApplicationMapper;
import com.cruise.game.model.entity.User;
import com.cruise.game.model.entity.WithdrawalApplication;
import com.cruise.game.model.param.user.WithdrawParam;
import com.cruise.game.model.vo.common.PageResult;
import com.cruise.game.model.vo.user.WithdrawalVO;
import com.cruise.game.service.agent.AgentWithdrawalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代理提现服务实现
 *
 * @author cruise
 * @date 2025-02-28
 */
@Slf4j
@Service
public class AgentWithdrawalServiceImpl implements AgentWithdrawalService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private WithdrawalApplicationMapper withdrawalApplicationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long submitWithdrawalApplication(Long userId, WithdrawParam param) {
        // 查询用户
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 验证提现金额
        if (param.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ApiException("提现金额必须大于0");
        }

        // 验证余额是否足够
        if (user.getBalance().compareTo(param.getAmount()) < 0) {
            throw new ApiException("余额不足");
        }

        // 扣减用户余额
        if (userMapper.deductBalance(userId, param.getAmount()) <= 0) {
            throw new ApiException("余额扣减失败，请重试");
        }

        // 创建提现申请
        WithdrawalApplication withdrawal = new WithdrawalApplication();
        withdrawal.setUserId(userId);
        withdrawal.setAmount(param.getAmount());
        withdrawal.setStatus("pending");
        withdrawal.setRemark(param.getRemark());
        withdrawal.setCreatedAt(LocalDateTime.now());
        withdrawal.setUpdatedAt(LocalDateTime.now());

        withdrawalApplicationMapper.insert(withdrawal);

        return withdrawal.getId();
    }

    @Override
    public PageResult<WithdrawalVO> getWithdrawalList(Long userId, String status, Integer page, Integer pageSize) {
        // 构建查询条件
        LambdaQueryWrapper<WithdrawalApplication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WithdrawalApplication::getUserId, userId);

        // 状态查询
        if (StringUtils.isNotBlank(status)) {
            queryWrapper.eq(WithdrawalApplication::getStatus, status);
        }

        // 排序
        queryWrapper.orderByDesc(WithdrawalApplication::getCreatedAt);

        // 分页查询
        IPage<WithdrawalApplication> withdrawalPage = withdrawalApplicationMapper.selectPage(
                new Page<>(page, pageSize),
                queryWrapper);

        // 转换为VO
        List<WithdrawalVO> withdrawalVOs = new ArrayList<>();
        for (WithdrawalApplication withdrawal : withdrawalPage.getRecords()) {
            WithdrawalVO vo = new WithdrawalVO();
            BeanUtils.copyProperties(withdrawal, vo);
            withdrawalVOs.add(vo);
        }

        // 构建分页结果
        return PageResult.of(withdrawalVOs, withdrawalPage.getTotal(), page, pageSize);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelWithdrawalApplication(Long userId, Long withdrawalId) {
        // 查询提现申请
        WithdrawalApplication withdrawal = withdrawalApplicationMapper.selectById(withdrawalId);

        if (withdrawal == null) {
            throw new ApiException("提现申请不存在");
        }

        // 验证所有权
        if (!withdrawal.getUserId().equals(userId)) {
            throw new ApiException("无权操作此提现申请");
        }

        // 验证状态
        if (!"pending".equals(withdrawal.getStatus())) {
            throw new ApiException("只能取消待处理的提现申请");
        }

        // 更新提现申请状态
        withdrawal.setStatus("cancelled");
        withdrawal.setUpdatedAt(LocalDateTime.now());

        boolean success = withdrawalApplicationMapper.updateById(withdrawal) > 0;

        if (success) {
            // 返还用户余额
            userMapper.updateBalance(userId, withdrawal.getAmount());
        }

        return success;
    }

    @Override
    public Map<String, Object> getWithdrawalStatistics(Long userId) {
        Map<String, Object> statistics = new HashMap<>();

        // 总提现金额
        BigDecimal totalAmount = withdrawalApplicationMapper.sumAmountByUserIdAndStatus(userId, "approved");
        statistics.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);

        // 待处理提现金额
        BigDecimal pendingAmount = withdrawalApplicationMapper.sumAmountByUserIdAndStatus(userId, "pending");
        statistics.put("pendingAmount", pendingAmount != null ? pendingAmount : BigDecimal.ZERO);

        // 本月提现金额
        LocalDateTime firstDayOfMonth = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth()).withHour(0)
                .withMinute(0).withSecond(0);
        LocalDateTime lastDayOfMonth = LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth()).withHour(23)
                .withMinute(59).withSecond(59);

        BigDecimal monthlyAmount = withdrawalApplicationMapper.sumAmountByUserIdAndStatusAndTimeRange(
                userId, "approved", firstDayOfMonth, lastDayOfMonth);
        statistics.put("monthlyAmount", monthlyAmount != null ? monthlyAmount : BigDecimal.ZERO);

        // 成功提现次数
        int successCount = withdrawalApplicationMapper.countByUserIdAndStatus(userId, "approved");
        statistics.put("successCount", successCount);

        // 待处理提现次数
        int pendingCount = withdrawalApplicationMapper.countByUserIdAndStatus(userId, "pending");
        statistics.put("pendingCount", pendingCount);

        // 已取消提现次数
        int cancelledCount = withdrawalApplicationMapper.countByUserIdAndStatus(userId, "cancelled");
        statistics.put("cancelledCount", cancelledCount);

        // 被拒绝提现次数
        int rejectedCount = withdrawalApplicationMapper.countByUserIdAndStatus(userId, "rejected");
        statistics.put("rejectedCount", rejectedCount);

        return statistics;
    }
}